home *** CD-ROM | disk | FTP | other *** search
- Path: uunet!tektronix!tekgen!tekred!games
- From: games@tekred.CNA.TEK.COM
- Newsgroups: comp.sources.games
- Subject: v06i061: cubes2 - a networked dice game (version 5.1), Part03/08
- Message-ID: <3902@tekred.CNA.TEK.COM>
- Date: 27 Apr 89 19:21:36 GMT
- Sender: billr@tekred.CNA.TEK.COM
- Lines: 1941
- Approved: billr@saab.CNA.TEK.COM
-
- Submitted-by: gmp@rayssdb.RAY.COM (Gregory M. Paris)
- Posting-number: Volume 6, Issue 61
- Archive-name: cubes2/Part03
-
-
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 3 (of 8)."
- # Contents: cubes.long.6 moniker.c tempers.c
- # Wrapped by billr@saab on Thu Apr 27 12:13:36 1989
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'cubes.long.6' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'cubes.long.6'\"
- else
- echo shar: Extracting \"'cubes.long.6'\" \(26844 characters\)
- sed "s/^X//" >'cubes.long.6' <<'END_OF_FILE'
- X.TH CUBES.LONG 6 "cubes 5.1" GMP "UNIX Gaming Manual"
- X.SH NAME
- Xcubes.long \- the nitty-gritty details of the game of cubes
- X.\"
- X.\" sccsid: @(#)cubes.long.6 5.1 (G.M. Paris) 89/01/22
- X.\"
- X.\"
- X.\"
- X.\" cubes 5.1 Copyright 1988 Gregory M. Paris
- X.\" Permission granted to redistribute on a no charge basis.
- X.\" All other rights are reserved.
- X.\"
- X.\"
- X.SH SYNOPSIS
- X.B cubes
- X[
- X.BR \- [ F ]{ BS }
- X] [
- X.B \-s
- X] [
- X.BR \- { pw }
- X] [
- X.B \-g graphics
- X] [
- X.B \-f cubehist
- X] [
- X.B \-h cubehost
- X] [
- X.B cubename
- X]
- X.SH OVERVIEW
- X[ Note: This is the long and complicated manual page for
- X.IR cubes ,
- Xwhich exists for the purpose of detailing the finer points of the game.
- XIf you are a beginner at
- X.IR cubes ,
- Xthe shorter manual page,
- X.IR cubes (6),
- Xshould be all you need to start playing the game. ]
- X.PP
- XThe game of
- X.I cubes
- Xis a computer implementation of a dice game played with
- Xfive six-sided dice.
- XThe goal of the game is to be the first player to
- Xscore
- X.I Win Score
- Xpoints (usually 10,000).
- XPlayers take turns rolling the dice in the hopes of getting one or more
- Xof several scoring combinations.
- XA player can continue rolling as long as the previous roll produced
- Xa scoring combination.
- XFailing that,
- Xany points accumulated during the turn are lost and the player's turn ends.
- XBefore that happens,
- Xthe player may elect to quit rolling (prudently or cowardly),
- Xcausing the points accumulated during the turn
- Xto be added to the player's score.
- XIt takes about twenty minutes to play a single 10,000 point game.
- XContrary to what you might think by reading this manual page,
- X.I cubes
- Xis both easy to learn and easy to play.
- X.SH "BEGINNING A GAME"
- X.I Cubes
- Xis both a single-player and a multi-player game,
- Xwith the game logic implemented in a cube server,
- Xand player interaction via a client process, the
- X.I cubes
- Xprogram.
- XFor more than one person to play at a time,
- Xeach must each begin
- X.I cubes
- Xat nearly the same time, and must connect to the same server.
- X.PP
- XThere are two
- X.I cubes
- Xgame modes:
- X.I Standard
- Xand
- X.IR Blitz .
- XThe first corresponds to games played to 10,000 points;
- Xthe second to shorter games played to 7,500 points.
- XSupplying the
- X.B \-B
- Xor
- X.B \-S
- Xoption informs the server that you'd prefer to play
- X.I Blitz
- Xmode or
- X.I Standard
- Xmode games respectively.
- XThe
- X.B \-FB
- X.RI ( Force \ Blitz )
- Xor
- X.B \-FS
- X.RI ( Force \ Standard )
- Xoption informs the server that you will play only
- X.I Blitz
- Xor
- X.I Standard
- Xmode games respectively.
- XYour preference may be taken into account when the server
- Xdecides the mode for each game.
- XIf the server does not honor your preference
- Xand if you specified one of the forced preferences,
- Xthe server will reject you.
- XIf you do not supply a preference option,
- Xthe server assumes you have no preference.
- X.PP
- XIf
- X.I cubes
- Xis invoked with the
- X.B \-s
- X(spider mode) option,
- Xand if there are no humans already playing,
- Xthe program will hang,
- Xwaiting for another human to begin a game.
- X(You may wish to suspend
- X.I cubes
- Xat this point -- the program will alert you by
- Xringing your terminal bell when a game is about to begin.)\
- XIf you get tired of waiting for another player,
- Xyou can quit waiting and begin a game by typing the letter
- X.RB ` g '
- Xfor `go'.
- XYou also can quit waiting with an interrupt,
- Xwhich will cause
- X.I cubes
- Xto exit, with no penalty to your ranking.
- X.PP
- XWhen a person enters a game already in progress
- X(explained more fully below),
- X.I cubes
- Xwill add that person as a watcher.
- XThe watcher can join the game using
- X.RB ` g '
- Xfor `go'.
- XThis step can be skipped by supplying
- X.RB ` \-p '
- Xswitch on the command line, causing
- X.I cubes
- Xthe user to be added as a player, rather than as a watcher.
- X.PP
- XIf your terminal supports DEC or Zenith graphics mode,
- Xyou can tell
- X.I cubes
- Xto take advantage of the graphics when drawing the screen.
- X(This feature assumes that the
- X.RB ` as '
- Xand
- X.RB ` ae '
- Xtermcap capabilities describe how to put your terminal into and take it out of
- Xgraphics mode.)\
- XTo do this, supply the
- X.RB ` \-g \ graphics '
- Xoption on the command line, where
- X.B graphics
- Xis one of
- X.RB ` d '
- Xfor DEC graphics,
- Xor
- X.RB ` z '
- Xfor Zenith graphics.
- XThe
- X.B \-g
- Xoption need not be supplied if your terminal's termcap
- Xentry specifies the
- X.RB ` Cg '
- X.RI ( C ubes
- X.IR g raphics)
- Xstring capability to be a letter corresponding to
- Xone of the valid graphics types
- X.RB ( d
- Xor
- X.BR z ).
- X.PP
- XAfter each completed game,
- X.I cubes
- Xappends a single line to the file ``.cubehist'' in
- Xyour home directory.
- XThe line provides a summary of what the game did to your
- Xstanding with regard to other players of
- X.IR cubes .
- XIf you wish to change the location of this file,
- Xyou may do so with the
- X.RB ` \-f \ cubehist '
- Xcommand line option,
- Xor with the
- X.B CUBEHIST
- Xenvironment variable.
- XThe command line option overrides the environment variable setting.
- XTo disable the feature entirely, specify a null filename.
- X.PP
- XThe
- X.I cubes
- Xprogram assumes that the server is on the same system as the player.
- XIf this is not so, the
- X.RB ` \-h \ cubehost '
- Xoption can be used to tell
- X.I cubes
- Xwhich system the server is running on.
- XIf you normally connect to a server on another system,
- Xyou may find it more convenient to set the
- X.B CUBEHOST
- Xenvironment variable to that system's name.
- X(The command line option overrides the environment variable.)
- X.PP
- XIf you'd like your name during the game
- Xto be something other than your login name,
- Xyou can supply a new name on the command line
- X(multi-word names need not be quoted).
- XIf you have a favorite name,
- Xyou can set the environment variable
- X.B CUBENAME
- Xto that value, which
- X.I cubes
- Xwill use when none is supplied on the command line.
- XIn either case,
- X.I cubes
- Xwill display only the first eighteen characters of the name.
- X.SH "PLAYING THE GAME"
- XThe rules of the game are described in more depth below.
- XFortunately, it is not necessary to understand the rules before playing
- X.IR cubes ,
- Xsince the cube server handles all that for you.
- XThe only thing to know before playing is what to do when prompted.
- X.PP
- XThe
- X.I cubes
- Xprogram will ask you only a few questions.
- XThe first question of each turn is
- X.PP
- X.B " Ready to roll? [yxe]"
- X.PP
- Xwhich is asking you to make the first roll of your turn.
- XThe letters
- X.RB ` yxe '
- Xindicate that the three valid answers are
- X.RB ` y '
- Xfor yes (to roll), and
- X.RB ` x '
- Xto enter autopilot mode (see
- X.B AUTOPILOT
- Xbelow),
- X.RB ` e '
- Xfor exit, to quit the game (see
- X.B QUITTING EARLY
- Xbelow).
- XThe default if you type just a carriage return is yes.
- X.PP
- XThe second question, of the form
- X.PP
- X.B " nnn saved, mmm showing; command? [rkhmabpxe]"
- X.PP
- Xis asking you whether you want to quit rolling or not,
- Xand if not, which dice you want to roll.
- XThe value of
- X.B nnn
- Xis the number of points you have from previous rolls.
- XThe value of
- X.B mmm
- Xis the number of points from the dice you just rolled.
- XIf you hold, the sum of
- X.B nnn
- Xand
- X.B mmm
- Xwill be added to your score.
- XTo hold, type
- X.RB ` h '
- Xand a carriage return.
- X.PP
- XIf you wish to roll again, you can type just a carriage return, and all
- Xnonscoring dice will be rerolled (or all dice, if they've all scored).
- XIf in addition to the nonscoring dice, you wish to roll some of the
- Xscoring dice, you can type
- X.RB ` r '
- Xfollowed by the die numbers.
- XThe
- X.RB ` r '
- Xis default, so you can omit it if you like (and you probably will).
- XAlso, if you omit the dice numbers, only the nonscoring dice will be rolled.
- XNote that the nonscoring dice always will be rolled,
- Xeven if you don't specify them explicitly,
- Xso there's really no point in doing so.
- X.PP
- XSometimes it may be more convenient to tell
- X.I cubes
- Xwhich dice you wish to keep rather than which dice you wish to roll.
- XTo do this,
- Xyou can type
- X.RB ` k '
- Xfollowed by a list of the dice you want to hold back.
- XIf no dice are specified, all scoring dice are kept and only nonscoring
- Xdice are rolled.
- X.PP
- XSome players find it advantageous to check the score file
- X(see
- X.B THE SCORE FILE
- Xbelow)
- Xbefore deciding whether to roll again or to hold.
- XFour commands are available for this purpose.
- XThey are
- X.RB ` m '
- Xfor my rank,
- X.RB ` a '
- Xfor above me,
- X.RB ` b '
- Xfor below me,
- Xand
- X.RB ` p < number >'
- Xfor player rank.
- XThese commands will cause
- X.I cubes
- Xto display the score file information for you,
- Xfor the player ranked immediately above you,
- Xfor the player ranked immediately below you,
- Xor for the selected player in the current game.
- X.PP
- XIf you are going to be temporarily interrupted,
- Xyou might want enter autopilot mode by answering
- Xwith
- X.RB ` x '.
- X.PP
- XYou also can type
- X.RB ` e '
- Xin response to this question,
- Xwhich will get you yet another question
- X.PP
- X.B " Do you really want to quit the game? [ny]"
- X.PP
- Xthe default answer being
- X.RB ` n '
- Xfor no.
- XYou should read the section titled
- X.B QUITTING EARLY
- Xbefore you answer
- X.RB ` y '
- Xto this question.
- X.PP
- XAt the conclusion of a game,
- X.I cubes
- Xwill prompt with
- X.PP
- X.B " Play another game? [ynmabp]"
- X.PP
- Xif you played in the last game, or if you were watching
- X.PP
- X.B " Play in next game? [ynmabp]"
- X.PP
- Xeither of which is asking you if you'd like to play in the next game.
- XThere is no default answer to this question because it is too easy
- Xto confuse this prompt with the "Ready to roll?" prompt,
- Xwhich is answered almost invariably with a carriage return.
- XThe
- X.RB ` m ',
- X.RB ` a ',
- X.RB ` b ',
- Xand
- X.RB ` p '
- Xcommands, as described above, are available for use at this prompt.
- X.SH "SCORING COMBINATIONS"
- XThe following is a description of each of the
- X.I cubes
- Xscoring combinations.
- XBelow, the word ``face'' is used as shorthand for face value.
- XFor a one, the face value is ten,
- Xand for a joker (see
- X.I Joker
- Xbelow) the face value is thirty.
- XFor all other faces, the face value is the same as the number of spots
- Xon the face, that is, two for a two, three for a three, etc.
- X.IP Points 12
- XDescription
- X.IP "300 * face"
- X.I Five of a Kind
- Xis the only combination that includes previously held dice.
- X.I Five of a Kind
- Xis all five dice showing the same face.
- XThis combination can occur any time the dice are rolled
- X(if any held dice are showing the same face).
- XSince held dice are part of the new combination,
- Xto not be counted twice,
- Xthe points for the old combination(s) are forgotten.
- XAll five dice score.
- X.IP 1500/750
- XA
- X.I Straight
- Xis an uninterrupted sequence of
- Xfive numbers, either one through five or two through six.
- XAll five dice score.
- XIf previously held dice are used in making a
- X.IR Straight,
- Xit is worth 750 points.
- XOtherwise, if all five dice were rolled to produce the
- X.IR Straight,
- Xit is worth 1500 points.
- X.IP "200 * face"
- X.I Four of a Kind
- Xis four rolled dice showing the same face.
- XThis combination can occur only when four or five dice are rolled.
- XFour dice score.
- X.IP 400
- XA
- X.I Small Straight
- Xis an uninterrupted sequence of four numbers.
- XThe possibilities are one through four, two through five, or three through six.
- XThis combination can occur only when four or five dice are rolled.
- XFour dice score.
- X.IP "100 * face"
- X.I Three of a Kind
- Xis three rolled dice showing the same face.
- XThis combination can occur when three, four, or five dice are rolled.
- XThree dice score.
- X.IP 100
- XAny
- X.IR One ,
- Xnot part of another combination, is a scoring combination unto itself.
- XA
- X.I One
- Xcan occur at any time.
- XEach
- X.I One
- Xis a scoring die.
- X.IP 50
- XAny
- X.IR Five ,
- Xnot part of another combination, is a scoring combination unto itself.
- XA
- X.I Five
- Xcan occur at any time.
- XEach
- X.I Five
- Xis a scoring die.
- X.IP 0
- XAny
- X.IR Joker ,
- Xnot part of another combination, is a scoring combination unto itself,
- Xbut unlike the
- X.I One
- Xand
- X.IR Five ,
- Xa single
- X.I Joker
- Xis not worth any points.
- XHowever, the face value of a
- X.I Joker
- Xis a whopping thirty, thus making
- X.IR Three ,
- X.IR Four ,
- Xand
- X.I Five of a Kind
- Xin
- X.I Jokers
- Xworth 3000, 6000, and 9000 points respectively.
- X.B Note:
- Xnot all cube servers will be configured to play
- X.I cubes
- Xwith dice that have
- X.I Jokers
- Xon them, and even if so configured,
- Xwill not play all games with such dice.
- XIf the game is to be played with
- X.I Joker
- Xdice, you will be notified before the game begins
- X(or when you enter, if the game is in progress).
- XYou may think of these dice as having thirteen sides,
- Xwith two of each of the faces one through six,
- Xand one
- X.I Joker
- Xface.
- X.SH "ROLLING THE DICE"
- XEach turn starts with the player rolling all five dice.
- XWhenever the dice are rolled, if no scoring combination appears,
- Xthe turn is over and any points accumulated during the turn are lost.
- XIf some dice score,
- Xthen the player can choose to roll again or to quit rolling.
- XWhen the player quits, the points accumulated during the turn are
- Xadded to the player's score.
- XThis is the only way to score points.
- X.PP
- XWhen rerolling, all nonscoring dice are always part of the reroll.
- XIf more than one scoring combination occurred on the prior roll,
- Xthe player also may choose to reroll some scoring dice,
- Xwith the restriction that at least one scoring combination must be held back.
- XWhen scoring dice are rerolled,
- Xthe points for the combinations they were part of are not added to
- Xthe accumulated turn points.
- X.PP
- XWhen all five dice score, either in a single roll or in multiple rolls,
- Xthe player may continue rolling with all five dice.
- XThis is the same as beginning the turn afresh,
- Xexcept that the turn points earned so far are retained (but are still
- Xvulnerable to being lost).
- X.PP
- XA player must quit rolling at some time to earn points on the scoreboard,
- Xbut there are two times when the player cannot quit.
- XThe first time is when the player has zero points, or in other words,
- Xis not yet on the scoreboard.
- XThe player must score at least 500 points in a turn to get
- X.I On Board
- Xand cannot quit before earning those points.
- XSimilarly, to get
- X.IR Off \ Board ,
- Xor cross the
- X.I Win Score
- Xline, the player needs at least 500 turn points.
- XThis threshold need be matched only when trying to cross
- X.I Win Score
- Xpoints;
- Xonce beyond, the player can quit with any number of turn points.
- X.SH "WINNING THE GAME"
- XA player with
- X.I Win Score
- Xpoints or more at the end of a round of
- Xturns is the winner, but only if that player's score exceeds
- Xthe next best score by a
- X.I Win Margin
- Xof 250 points.
- XWhile this condition is not met, play continues.
- X.I Cubes
- Xwill warn of a player's impending win.
- X.PP
- XNormally, 10,000 points is the
- X.IR Win \ Score ,
- Xor minimum score, needed to win a game.
- XOn some systems, however, the cube server may be configured
- Xto run in
- X.I Blitz
- Xmode during some parts of the day (usually working hours),
- Xor when all players with a preference desire to play in
- X.I Blitz
- Xmode.
- X(See
- X.IR cubeserver (6)
- Xfor more details.)
- XIn a
- X.I Blitz
- Xmode game,
- X.I Win Score
- Xwill be less than 10,000 points,
- Xusually 7,500 points (unless changed at compile time).
- XA reduced
- X.I Win Score
- Xmakes for shorter, but riskier games
- Xsince there's less time to catch up if you get behind,
- Xand also because entries made to the score file are
- Xscaled to 10,000 points \- thus making a loss by 500 points
- Xinto a recorded loss by 750 points, if
- X.I Win Score
- Xis 7,500 points.
- X(This effect cuts both ways, however, since a win
- Xis also scaled up to being a bigger win.)\
- XThe current
- X.I Win Score
- Xis always displayed on the screen,
- Xand is set only at the beginning of each game.
- X.SH "COMPUTER PLAYERS"
- XSince it would be pointless to play the game alone,
- Xthe cube server provides some automatic competition as one or
- Xmore computer players.
- XOne such player,
- X.BR \s-2CUBEX\s+2 ,
- Xplays in every game,
- Xbut depending on the number of human players and some random factors,
- Xone or more additional computer players also may join.
- XEach computer player has its own distinct playing style that
- Xdoes not vary from game to game.
- XEach may also have a preference for
- X.I Standard
- Xor
- X.I Blitz
- Xmode games, though most have no preference.
- XTheir competence ranges from mildly so to expert,
- Xbut no matter how it may seem at times,
- Xthe game is not rigged in their favor.
- X.SH "THE SCORE FILE"
- XThe cube server keeps a score file that contains information about each
- Xhuman and computer player that has played
- X.I cubes
- Xon that system.
- XRegardless of the name chosen to display on the scoreboard,
- Xhuman players are recorded in the score file by login name.
- XComputer players are recorded by their one and only name.
- XAn auxiliary program called
- X.IR cuberank (6)
- Xis provided to display the contents of this system's
- X.I cubes
- Xscore file.
- X.PP
- XAs a convenient mechanism for keeping track of your personal ranking
- Xhistory,
- X.I cubes
- Xwill append your current ranking information to the file ".cubehist"
- Xin your home directory
- X(as specified by the
- X.B HOME
- Xenvironment variable)
- Xafter each game played to completion.
- X.SH "JOINING A GAME IN PROGRESS"
- XA person may join a game in progress as either a new player,
- Xor as an unnamed observer.
- XIf the game is near ending
- X(defined as the high score being 75% or more of the
- X.IR Win \ Score ),
- Xor if the
- X.RB ` \-p '
- Xcommand line option was not specified,
- Xyou will be added to the game as an observer.
- XWhen the current game ends,
- Xwill be asked whether you wish to play in the next game.
- XYou can join the game in progress with the
- X.RB ` g '
- Xcommand.
- XIf you choose to play,
- Xyou will be added as an active player at the end of the current round
- Xand you will appear as the first player in the turn order.
- XSince coming into a game late with no points could ruin your ranking,
- Xthe cube server will give you an initial score
- Xthat is 500 points less than the lowest score,
- Xbut you still must meet the
- X.I On Board
- Xturn point requirement to begin advancing your score.
- X.PP
- XComputer players will sometimes join particularly close games in progress.
- XChalk it up to love of excitement, if you must.
- X.SH "QUITTING EARLY"
- XIt is important to note that quitting a game before it ends
- Xwill probably result in a low score being added to your record,
- Xpossibly lowering your ranking against other players.
- XExcept as described in the next paragraph,
- Xif you quit a game before you get
- X.IR On \ Board ,
- Xyour average game point value,
- X.I GamPt
- X(see
- X.IR cuberank (6)),
- Xis penalized by being adjusted to the value you would have had if
- Xyou had stayed in the game and lost with a score of half your average.
- XThis adjustment is done by subtracting points from your cumulative point record;
- Xyour game count and other records are not altered.
- XExcept as described in the next paragraph,
- Xif you quit a game when you are
- X.IR On \ Board ,
- Xyour current score is recorded in the score file.
- X.PP
- XIn games with more than one human player,
- Xit is possible that a computer proxy will take over for
- Xa player that quits the game early.
- XThe chances of this happening are 20% if the exiting player is not
- X.IR On \ Board ,
- Xand 60% if the player is
- X.IR On \ Board .
- XProxies play with a somewhat erratic style,
- Xso they should be almost indiscernible from humans.
- XNo notice is given to anybody when a proxy takes over.
- XThe absentee player will be credited with the score that the proxy
- Xmanages to attain by game end (for good or bad).
- X.PP
- XThe cube server will not conduct a game that has no human players.
- XTo meet that requirement,
- Xwhen the only human player quits the game,
- Xno proxy is assigned and the game is ended at that point.
- XThe human player's score will be recorded in the score file
- Xonly if that player was
- X.I On Board
- Xat the time of quitting.
- XThe scores of the computer players (proxies are included in this category)
- Xare not recorded,
- Xregardless of their
- X.I On Board
- Xstatus.
- XIn short, if the only human player quits a game before getting
- X.IR On \ Board ,
- Xno record of the game is added to the score file,
- Xalthough the human player will suffer the penalty described above.
- X.PP
- XUnlike previous versions of this game,
- Xthere is no point at which it is safe to quit early.
- XThere is always a risk, if not a certainty, of being penalized for quitting.
- X.PP
- XSome computer players, like cowardly human players,
- Xquit rather than get
- X.I On Board
- Xvery far behind,
- Xsuffering the same penalty that humans do when they quit.
- XOnce the high score has reached 25% of the
- X.IR Win \ Score ,
- Xbefore each turn, computer players that are not
- X.I On Board
- Xdecide whether to continue in the game.
- XIf the computer needs more points to reach its average
- Xthan the leader needs to win, the computer may quit.
- X.BR \s-2CUBEX\s+2 ,
- Xbeing oblivious to other players,
- Xand possessing a singularly strong desire to play
- X.IR cubes ,
- Xwill not quit the game.
- XIt should be noted that proxy players also will not quit a game.
- X.SH AUTOPILOT
- XA game of
- X.I cubes
- Xusually takes about 20 minutes to play.
- XStrangely, starting a game of
- X.I cubes
- Xseems to generate phone calls and visits from associates demanding
- Xattention.
- XTo allow players to deal with interruptions,
- Xthere is an autopilot mechanism provided.
- XThe command to invoke the autopilot is
- X.RB ` x '
- Xand can be used during your turn, or asynchronously.
- XYou'll probably want to suspend
- X.I cubes
- Xwith a control-Z once you engage the autopilot.
- XThe autopilot will play for you until you type
- X.RB ` g '
- Xfor go.
- X.PP
- XIt should be noted that the autopilot is not a very good player.
- X.SH MISCELLANY
- XOn some systems,
- Xit is possible to tell the state of the cube server by doing a
- X.IR ps (1)
- X(or something similar) on it.
- XIf a game is in progress,
- Xthe command line of the process will have been altered to
- Xshow the number of players, turn number, high score, and player up.
- XEven more useful is an auxiliary program, called
- X.IR cubestat (6),
- Xthat produces a more detailed report of the server status.
- X.PP
- XThe last player in the turn order has somewhat of an advantage.
- XTherefore,
- X.I cubes
- Xuses player order as a reward for good playing.
- XWhen a game is begun after the cube server has been idle,
- Xthe players will be ordered in reverse-rank order (top-ranked player last).
- XIn subsequent games, players will be ordered based on the score from
- Xthe previous game, with best score last.
- XAny player that joins a game in progress,
- Xor begins in a game that contains players from a just ended game,
- Xis put at the beginning of the turn order.
- XIf more than one such player enters a game on the same turn,
- Xthe new players will be added to the beginning of the turn order,
- Xbut, amongst themselves, will be ordered in reverse-rank order.
- X.PP
- XA control-Z (or whatever your suspend character is) will cause
- X.I cubes
- Xto return you to the shell,
- Xassuming that your shell supports job control.
- XThe
- X.I cubes
- Xprocess will continue to run silently in the background,
- Xbut will beep your terminal whenever you are being prompted.
- XBring
- X.I cubes
- Xback to the foreground (usually by typing
- X.RB ` fg ')
- Xto resume play at the current point in the game.
- X.PP
- XShould the screen become garbled,
- Xit can be redrawn by typing control-L
- Xor, if you prefer, your terminal reprint character (usually control-R).
- XThere may be a slight delay before
- X.I cubes
- Xresponds to the screen redraw request.
- X.PP
- XTo keep the game moving,
- Xthere is a sixty second timeout on every question asked by
- X.IR cubes .
- XThe program will beep your terminal bell every twenty
- Xseconds until the timeout is reached.
- XAlthough the program tries to handle timeouts gracefully
- Xand may engage the autopilot automatically
- Xif you wait too long to roll.
- X.PP
- XWhen rerolling,
- Xthere are some synonyms for the four commands;
- Xyou may find some more convenient to type.
- XFor hold,
- Xthe synonyms are
- X.RB ` q '
- Xfor quit rolling,
- X.RB ` n '
- Xfor no (don't roll again),
- Xand
- X.RB ` . '
- X(period) for those who like to use a numeric keypad.
- XFor roll,
- Xthere is a synonym of
- X.RB ` t '
- Xfor throw.
- XFor keep there is
- X.RB ` s '
- Xfor save,
- Xand, for the numeric keypad crowd,
- X.RB ` , '
- X(komma, er rather, comma).
- X.PP
- XThe cube server uses a pseudorandom number generator to generate the die rolls.
- XUnlike real life, it is possible to see what a player would have rolled
- Xby looking at what the following player rolls.
- XFor instance, if a player debates whether to roll three dice,
- Xthen decides to hold, that player can check dice one, two, and three
- Xon the following player's roll to see what would have been rolled.
- XThis type of hindsight is not available in the physical world.
- X.PP
- XIf you wish to use a shell script to invoke
- X.IR cubes ,
- Xthe script must take into account that
- X.I cubes
- Xchanges the meaning of the interrupt and quit signals.
- XYour shell script must not respond to these signals.
- XOne way to accomplish this is to have your shell script
- X.I exec cubes
- X(see
- X.IR sh (1)),
- Xthus avoiding the problem altogether,
- Xsince the shell script will ``vanish'' at the point of the
- X.IR exec .
- XBourne or Korn shell example:
- X.PP
- X.nf
- X exec /usr/games/cubes "$@"
- X.fi
- X.PP
- XIf you have more processing that you wish to do after
- X.I cubes
- Xexits, the
- X.I exec
- Xmethod will not suffice.
- XInstead, your shell script must
- X.I trap
- Xand do nothing with (but NOT ignore)
- Xthe two signals in question.
- XBourne or Korn shell example:
- X.PP
- X.nf
- X trap : INT QUIT
- X /usr/games/cubes "$@"
- X /usr/games/cuberank -n5
- X.fi
- X.PP
- X(If you prefer to write your shell scripts using
- X.IR csh (1),
- Xyou're on your own...)
- X.SH HISTORY
- XThis game is an adaptation of a ``traditional'' dice game the author learned
- Xfrom a friend twelve years before writing this program.
- XIf the name of the game was learned at the time, it since has been forgotten.
- XThe name
- X.I cubes
- Xwas coined as the name of this computer implementation of the game.
- XIn the process of fine tuning the game of
- X.IR cubes ,
- Xsome liberties have been taken with the rules as learned.
- XWhat follows is a list of differences between
- X.I cubes
- Xand the original (name unknown) dice game.
- X.IP (1) 4
- XThe 500 point
- X.I Off Board
- Xthreshold did not exist in the original.
- XNo minimum turn score was necessary to cross
- X.I Win Score
- Xpoints.
- X.IP (2)
- XThe 250 point
- X.I Win Margin
- Xdid not exist in the original.
- XThe player with the highest score (at or above
- X.IR Win \ Score ,
- Xof course)
- Xat the end of the round was the winner.
- X.IP (3)
- XThe scoring combination of
- X.I Four of a Kind
- Xdid not exist in the original.
- X.IP (4)
- XThe scoring combination
- X.I Small Straight
- Xdid not exist in the original.
- X.IP (5)
- XIn the original,
- X.I Five of a Kind
- Xcould be scored only in ones or fives.
- X(Even in
- X.IR cubes ,
- Xscoring
- X.I Five of a Kind
- Xin anything other than ones or fives is rare.)
- X.IP (6)
- XScoring a
- X.I Straight
- Xin multiple rolls has been added by popular demand.
- XIt turns out that this combination adds quite a bit
- Xmore strategy to the game.
- X(Hint: compute the probabilities.)
- X.IP (7)
- XIn the original game, there were no computer players!
- X.IP (8)
- XQuitting as a tactic to preserve ranking is a seemingly
- Xunavoidable side effect of this implementation of the game.
- XIn the real life dice game, people usually don't up and quit,
- Xeven if they start out way behind.
- XThe quitting penalty is the fairest way, so far devised,
- Xto mimic the peer pressure of a real life game.
- X.SH "ENVIRONMENT VARIABLES"
- X.DT
- X.nf
- XHOME home directory
- XUSER login name
- XCUBEHIST default ranking history file
- XCUBEHOST default server host
- XCUBENAME default player name
- X.fi
- X.SH FILES
- X.DT
- X.nf
- X$HOME/.cubehist user's ranking history file
- X.fi
- X.SH "SEE ALSO"
- Xcubes(6), cuberank(6), cubestat(6), cubeserver(6), ps(1), sh(1), termcap(5)
- X.SH AUTHOR
- XGreg Paris <gmp@rayssd.ray.com>
- END_OF_FILE
- if test 26844 -ne `wc -c <'cubes.long.6'`; then
- echo shar: \"'cubes.long.6'\" unpacked with wrong size!
- fi
- # end of 'cubes.long.6'
- fi
- if test -f 'moniker.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'moniker.c'\"
- else
- echo shar: Extracting \"'moniker.c'\" \(3417 characters\)
- sed "s/^X//" >'moniker.c' <<'END_OF_FILE'
- X/* vi:set sw=4 ts=4: */
- X#ifndef lint
- Xstatic char sccsid[] = "@(#)moniker.c 5.1 (G.M. Paris) 89/01/22";
- X#endif lint
- X
- X/*
- X**
- X** cubes 5.1 Copyright 1989 Gregory M. Paris
- X** Permission granted to redistribute on a no charge basis.
- X** All other rights are reserved.
- X**
- X*/
- X
- X#include <stdio.h>
- X#include <syslog.h>
- X#include <strings.h>
- X#include "cubes.h"
- X
- X#ifdef lint
- X#ifndef MONFILE
- X#define MONFILE "dummy-monfile"
- X#endif MONFILE
- X#endif lint
- X
- Xstruct mon {
- X char m_name[NAMELEN];
- X struct mon *m_next;
- X};
- X
- X/*
- X** seed: names to seed the moniker list
- X*/
- Xstatic struct mon seed[] = {
- X { "Ronald Reagan", seed+ 1 },
- X { "Nancy Reagan", seed+ 2 },
- X { "George Bush", seed+ 3 },
- X { "Barbara Bush", seed+ 4 },
- X { "Mikhail Gorbachev", seed+ 5 },
- X { "Raisa Gorbachev", seed+ 6 },
- X { "Benny Hill", seed+ 7 },
- X { "Margaret Thatcher", seed+ 8 },
- X { "Piotr Chekov", seed+ 9 },
- X { "Jamie Finney", seed+10 },
- X { "Touche Turtle", seed+11 },
- X { "Judy Jetson", seed+12 },
- X { "Cobb Anderson", seed+13 },
- X { "Della Taze", seed+14 },
- X { "Mickey Mouse", seed+15 },
- X { "Minnie Mouse", seed+16 },
- X { "Edison Carter", seed+17 },
- X { "Theora Jones", 0 },
- X};
- X
- Xstatic int seedcnt = sizeof seed / sizeof seed[0];
- Xstatic struct mon *monlist = 0;
- Xstatic int moncnt = 0;
- X
- Xextern char *malloc();
- Xextern char *fgets();
- Xextern computer *compbyname();
- X
- X/*
- X** savename: add a name to the moniker list and save the new list
- X*/
- Xsavename(name)
- Xchar *name;
- X{
- X register struct mon *m;
- X FILE *fp;
- X
- X if(monlist == 0)
- X readmonfile();
- X
- X if(strlen(name) < 5) /* small names are boring */
- X return;
- X if(compbyname(name) != 0) /* don't save computer names */
- X return;
- X
- X /*
- X ** Check for duplicate while finding the end of the list.
- X */
- X for(m = monlist;;m = m->m_next) {
- X if(strncmp(name, m->m_name, NAMELEN) == 0)
- X return;
- X if(m->m_next == 0)
- X break;
- X }
- X
- X /*
- X ** Add the new name to the end of the list.
- X */
- X if((m->m_next = (struct mon *)malloc(sizeof *m)) == 0) {
- X syslog(LOG_WARNING, "savename: out of memory");
- X return;
- X }
- X m = m->m_next;
- X m->m_next = 0;
- X strncpy(m->m_name, name, NAMELEN);
- X m->m_name[NAMELEN-1] = '\0';
- X ++moncnt;
- X
- X /*
- X ** Append the new name to the monikers file.
- X */
- X (void) umask(022);
- X if((fp = fopen(MONFILE, "a")) == 0) {
- X syslog(LOG_WARNING, "savename: fopen(%s,a): %m", MONFILE);
- X return;
- X }
- X fprintf(fp, "%s\n", m->m_name);
- X (void) fclose(fp);
- X}
- X
- X/*
- X** moniker: randomly select a name from the moniker list
- X*/
- Xchar *
- Xmoniker()
- X{
- X register struct mon *m;
- X register int n;
- X
- X if(monlist == 0)
- X readmonfile();
- X
- X n = randint(moncnt) - 1;
- X for(m = monlist;n > 0 && m->m_next != 0;--n, m = m->m_next)
- X ;
- X
- X return m->m_name;
- X}
- X
- X/*
- X** readmonfile: seed the monikers list then read in the monikers file
- X*/
- Xreadmonfile()
- X{
- X register struct mon *m;
- X register FILE *fp;
- X char *s, line[2*NAMELEN];
- X
- X monlist = &seed[0];
- X moncnt = seedcnt;
- X
- X if((fp = fopen(MONFILE, "r")) == 0) {
- X syslog(LOG_WARNING, "readmonfile: fopen(%s,r): %m", MONFILE);
- X return;
- X }
- X
- X for(m = monlist;m->m_next != 0;++m)
- X ;
- X
- X while(fgets(line, sizeof line, fp) != 0) {
- X if(*(s = &line[strlen(line)-1]) == '\n')
- X *s = '\0';
- X if((m->m_next = (struct mon *)malloc(sizeof *m)) == 0) {
- X syslog(LOG_WARNING, "readmonfile: out of memory");
- X return;
- X }
- X m = m->m_next;
- X m->m_next = 0;
- X strncpy(m->m_name, line, NAMELEN);
- X m->m_name[NAMELEN-1] = '\0';
- X ++moncnt;
- X }
- X
- X (void) fclose(fp);
- X}
- END_OF_FILE
- if test 3417 -ne `wc -c <'moniker.c'`; then
- echo shar: \"'moniker.c'\" unpacked with wrong size!
- fi
- # end of 'moniker.c'
- fi
- if test -f 'tempers.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'tempers.c'\"
- else
- echo shar: Extracting \"'tempers.c'\" \(21222 characters\)
- sed "s/^X//" >'tempers.c' <<'END_OF_FILE'
- X/* vi:set sw=4 ts=4: */
- X#ifndef lint
- Xstatic char sccsid[] = "@(#)tempers.c 5.1 (G.M. Paris) 89/01/22";
- X#endif lint
- X
- X/*
- X**
- X** cubes 5.1 Copyright 1989 Gregory M. Paris
- X** Permission granted to redistribute on a no charge basis.
- X** All other rights are reserved.
- X**
- X*/
- X
- X#include <syslog.h>
- X#include "cubes.h"
- X
- Xextern unsigned nhist;
- Xextern history *hist;
- Xextern int winscore;
- Xextern int turnnum;
- Xextern boolean jokermode;
- Xextern player plr[];
- Xextern double ziprisk();
- Xextern int highscore();
- Xextern int closescore();
- Xextern int winner();
- Xextern long histavgplr();
- X
- X#define P_MAXROLL (P_ACEMULT * P_AOKMULT) /* largest single roll */
- X
- X/*
- X** atbreakeven: returns True if player has reached the quit-penalty
- X** break-even point (roughly half of player's point average)
- X** or can be expected to reach it before the game ends
- X*/
- Xboolean
- Xatbreakeven(comp, mscore, hscore)
- Xint comp, mscore, hscore;
- X{
- X long half, need;
- X
- X if((half = histavgplr(comp)) == 0) /* no average */
- X return True; /* passed it, right? */
- X half = (half * winscore) / (2 * WINSCORE); /* derate and half */
- X if((need = half - mscore) <= 0) /* passed it? */
- X return True;
- X if(winscore - hscore > 2 * need) /* probably can reach it? */
- X return True;
- X return False; /* not yet */
- X}
- X
- X/*
- X** robot: just plays the expectations and ignores other players, etc.
- X*/
- X/*ARGSUSED*/
- Xstatic boolean
- Xrobot(comp, stay, xpct, pd)
- Xint comp, stay, xpct;
- Xdiceset *pd;
- X{
- X /*
- X ** Don't roll if there's no advantage.
- X */
- X return (xpct <= stay) ? False : True;
- X}
- X
- X/*
- X** xx_antsy: gets antsy when it gets behind; uses supplied tracking function
- X** a little bit more conservative than robot when ahead
- X*/
- X/*ARGSUSED*/
- Xstatic boolean
- Xxx_antsy(comp, stay, xpct, pd, track)
- Xint comp, stay, xpct;
- Xdiceset *pd;
- Xint (*track)();
- X{
- X int mscore;
- X int hscore, hc;
- X double livefac;
- X
- X#define TOOLITTLE (2 * P_ACE)
- X#define GAINFAC 1.1
- X#define WAYBEHIND ((P_MAXROLL * winscore) / WINSCORE)
- X#define CLOSE WINMARGIN
- X#define AVGTURN 400 /* empirically derived */
- X#define SANITY 0.40
- X
- X /*
- X ** Avoid starting out too far in the hole by not getting on board
- X ** way behind -- the leave-the-game algorithm will eventually "save"
- X ** us, but we pay a price. We know what the price is, so if we
- X ** reach the break-even point, we hold.
- X */
- X mscore = plr[comp].p_score + stay;
- X if(plr[comp].p_onboard == False /* && stay >= ONBOARD */) {
- X hscore = highscore(comp, (int *)0); /* not (*track) */
- X if(hscore - mscore > WAYBEHIND) {
- X if(atbreakeven(comp, mscore, hscore) == True)
- X return False; /* hold */
- X return True; /* desperation */
- X }
- X }
- X
- X /*
- X ** Never stop with too little points.
- X */
- X if(stay <= TOOLITTLE)
- X return True;
- X
- X /*
- X ** If there's gain to be had, roll again.
- X */
- X if(xpct > (int)(GAINFAC * stay))
- X return True;
- X
- X /*
- X ** Find our score and the score we're tracking. If we're ahead
- X ** or close, then don't reroll. Our definition of close depends
- X ** on whether the leader has already taken its turn this round.
- X */
- X hscore = (*track)(comp, &hc);
- X if(hc < comp) { /* leader has taken turn */
- X if(hscore - mscore <= CLOSE)
- X return False;
- X } else { /* leader's turn still to come */
- X if(hscore - mscore <= CLOSE - AVGTURN)
- X return False;
- X }
- X
- X /*
- X ** Calculate the expectation value we can live with.
- X */
- X livefac = GAINFAC - (double)(hscore - mscore) / winscore;
- X if(livefac < SANITY)
- X livefac = SANITY;
- X if(xpct > (int)(livefac * stay))
- X return True;
- X
- X return False;
- X
- X#undef TOOLITTLE
- X#undef GAINFAC
- X#undef WAYBEHIND
- X#undef CLOSE
- X#undef AVGTURN
- X#undef SANITY
- X}
- X
- X/*
- X** antsy: gets antsy when it gets behind; tracks leader
- X*/
- Xstatic boolean
- Xantsy(comp, stay, xpct, pd)
- Xint comp, stay, xpct;
- Xdiceset *pd;
- X{
- X return xx_antsy(comp, stay, xpct, pd, highscore);
- X}
- X
- X/*
- X** tracker: same as antsy but tracks highest close score rather than higest
- X*/
- Xstatic boolean
- Xtracker(comp, stay, xpct, pd)
- Xint comp, stay, xpct;
- Xdiceset *pd;
- X{
- X return xx_antsy(comp, stay, xpct, pd, closescore);
- X}
- X
- X/*
- X** chicken: gets scared when it has lots of points in hand
- X** doesn't care about expectation or other players
- X** also chickens out as soon as it thinks it has won
- X** won't get on board if high score is out of range
- X*/
- X/*ARGSUSED*/
- Xstatic boolean
- Xchicken(comp, stay, xpct, pd)
- Xint comp, stay, xpct;
- Xdiceset *pd;
- X{
- X int mscore, hscore, hc;
- X int atrisk, maxrisk;
- X int range, magic;
- X
- X#define OUTRNG ((P_STRAIGHT * winscore) / WINSCORE)
- X#define AVGTURN 375 /* empirically, a bit low */
- X
- X /*
- X ** We have the opportunity to get on board if we quit. We hold
- X ** if the high score is not out of range. We roll again if we
- X ** have no average, thus cannot be penalized. We hold if we've
- X ** reached the break-even point. Otherwise, roll again.
- X */
- X if(plr[comp].p_onboard == False /* && stay >= ONBOARD */) {
- X mscore = plr[comp].p_score + stay;
- X hscore = highscore(comp, &hc);
- X if(hc > comp)
- X hscore += AVGTURN;
- X if(hscore - mscore < OUTRNG)
- X return False; /* close enough, hold! */
- X if(atbreakeven(comp, mscore, hscore) == True)
- X return False; /* too risky to roll */
- X return True; /* desperation... */
- X }
- X
- X /*
- X ** If the leader's turn has already been taken, then if we
- X ** can win, hold. If the leader has yet to take its turn,
- X ** if we can block it from winning, hold. Adjust hscore
- X ** here for leader's predicted turn.
- X */
- X if((mscore = plr[comp].p_score + stay) >= winscore) {
- X hscore = highscore(comp, &hc);
- X if(hc < comp) { /* leader had turn */
- X if(mscore - hscore >= WINMARGIN) /* can we win? */
- X return False;
- X } else { /* leader's turn to come */
- X hscore += AVGTURN; /* predict future */
- X if(hscore - mscore < WINMARGIN) /* can we block? */
- X return False;
- X }
- X }
- X
- X /*
- X ** Our behavior is dependent on our mood.
- X */
- X switch(plr[comp].p_mood) {
- X case 2: magic = P_FIVE / 2; break;
- X case 3: magic = P_FIVE * 2; break;
- X default:magic = P_FIVE; break;
- X }
- X
- X /*
- X ** We are conservative when close, getting more desperate
- X ** as we get further behind. We get a little wild when
- X ** we're ahead too.
- X */
- X atrisk = (int)(stay * ziprisk(pd));
- X if((range = (mscore - hscore + 1) / WINMARGIN) <= 0)
- X maxrisk = ((1 - range) * magic); /* not winning */
- X else
- X maxrisk = (range * magic) / 3; /* winning */
- X if(maxrisk > 4 * magic)
- X maxrisk = 4 * magic;
- X
- X if(atrisk > maxrisk)
- X return False;
- X
- X return True;
- X
- X#undef OUTRNG
- X#undef AVGTURN
- X}
- X
- X/*
- X** gambler: cautious sometimes, not so others
- X** stops when it gets on board unless the risk is small or far behind
- X** stops when it has won or could block unless the risk is small
- X** rolls when the expectation is favorable
- X** rolls to try to stop a winner until too much at risk
- X** rolls when there's less than 50% risk and is behind and "lucky"
- X*/
- X/*ARGSUSED*/
- Xstatic boolean
- Xgambler(comp, stay, xpct, pd)
- Xint comp, stay, xpct;
- Xdiceset *pd;
- X{
- X int mscore, hscore, hc;
- X double luck;
- X
- X#define SMALLRISK 0.15
- X#define EVENODDS 0.50
- X#define FARBEHIND (winscore / 5)
- X#define AVGTURN (jokermode == True ? 350 : 450)
- X
- X /*
- X ** Calculate our score. Calculate the other highest score
- X ** and if the leader hasn't taken its turn yet, guess at
- X ** what that turn might amount to.
- X */
- X mscore = plr[comp].p_score + stay;
- X hscore = highscore(comp, &hc);
- X if(hc > comp) /* leader hasn't taken this turn */
- X hscore += AVGTURN; /* adjust for future earnings */
- X
- X /*
- X ** If we can get on board, we roll again anyway if we're
- X ** far behind. Otherwise, we hold unless it's really tempting.
- X */
- X if(plr[comp].p_onboard == False /* && stay >= ONBOARD */) {
- X if(hscore - mscore > FARBEHIND) {
- X if(atbreakeven(comp, mscore, hscore) == False)
- X return True; /* too risky to quit */
- X }
- X if(xpct > stay && ziprisk(pd) < SMALLRISK)
- X return True;
- X return False;
- X }
- X
- X /*
- X ** If we could win or block, hold unless it's really tempting.
- X */
- X if((mscore = plr[comp].p_score + stay) >= winscore) {
- X if( (hc < comp && mscore - hscore >= WINMARGIN) /* can win */
- X || (hc > comp && hscore - mscore < WINMARGIN)) { /* can block */
- X if(xpct > stay && ziprisk(pd) < SMALLRISK)
- X return True;
- X return False;
- X }
- X }
- X
- X /*
- X ** If the expectation value is better than what we've got, go ahead.
- X */
- X if(xpct > stay)
- X return True;
- X
- X /*
- X ** If another player is about to win, try to stop it. This isn't strictly
- X ** corrrect code, since we may not be the second-best score, but we can't
- X ** count on others to save us. We give up if we risk losing too much.
- X */
- X if(hscore >= winscore && hscore - mscore >= WINMARGIN)
- X return (int)(stay * ziprisk(pd)) > P_ASMSTR ? False : True;
- X
- X /*
- X ** If we're behind, roll when the odds are favorable and we feel lucky.
- X ** We feel lucky if we've been lucky -- if we've squandered less than
- X ** half of what we've scored, then we have some luck. If our luck
- X ** multiplied by our desperation is greater than what we'd have if
- X ** we held, then we roll.
- X */
- X if(hscore > mscore && mscore > 0 && ziprisk(pd) <= EVENODDS)
- X if((luck = 1.0 - (2.0 * plr[comp].p_squander) / mscore) > 0)
- X if(luck * (hscore - mscore) > stay)
- X return True;
- X
- X /*
- X ** Finally, don't hold with too few points.
- X */
- X return (stay < 2 * P_ACE) ? True : False;
- X
- X#undef SMALLRISK
- X#undef EVENODDS
- X#undef FARBEHIND
- X#undef AVGTURN
- X}
- X
- X/*
- X** xx_crafty:
- X** Won't get on board if too far behind.
- X** Quits when it can win, unless really tempting.
- X** Tries to roll to beat a winner.
- X** Otherwise, tries to get and protect a safelead lead
- X** becoming more daring as it gets ahead or behind,
- X** but with a limit to its stupidity.
- X*/
- X/*ARGSUSED*/
- Xstatic boolean
- Xxx_crafty(comp, stay, xpct, pd, safelead, maxgainfac, mingainfac, smallrisk)
- Xint comp, stay, xpct;
- Xdiceset *pd;
- Xint safelead;
- Xdouble maxgainfac, mingainfac, smallrisk;
- X{
- X int mscore, hscore;
- X int live, winc;
- X double gainfac;
- X
- X#define TOOFAC 4
- X
- X hscore = highscore(comp, (int *)0);
- X mscore = plr[comp].p_score + stay;
- X
- X /*
- X ** We can get on board here. If we're too far behind, and not
- X ** yet at the quit-penalty break-even point, we keep rolling.
- X ** If too risky, we hold. Otherwise, use the usual decision function.
- X */
- X if(plr[comp].p_onboard == False /* && stay >= ONBOARD */) {
- X if(hscore - mscore > TOOFAC * safelead) { /* too far behind */
- X if(atbreakeven(comp, mscore, hscore) == False)
- X return True; /* must roll */
- X }
- X if(ziprisk(pd) >= smallrisk) /* too risky */
- X return False; /* must hold */
- X }
- X
- X /*
- X ** If we could win, hold unless it's really tempting.
- X */
- X if(mscore >= winscore)
- X if(mscore - hscore >= WINMARGIN && ziprisk(pd) >= smallrisk)
- X return False;
- X
- X /*
- X ** If we have a winner (other than us), try to beat them, but only
- X ** if the expected gainfac is greater than or equal to mingainfac.
- X ** We try to get within WINMARGIN of the player's score,
- X ** but if their turn is after ours, we try to beat.
- X ** Assumes that hscore is winner's score (but what else?).
- X */
- X if((winc = winner()) != -1 && winc != comp)
- X if(xpct >= stay * mingainfac)
- X if(hscore - mscore >= WINMARGIN || winc > comp)
- X return True;
- X
- X /*
- X ** If there's enough gain to be had, roll again.
- X */
- X if(xpct > (int)(maxgainfac * stay))
- X return True;
- X
- X /*
- X ** Calculate the "instantaneous" gain factor. Changed gainfac
- X ** calculation to use p_score when ahead, since this temperament
- X ** used to routinely squander huge rolls.
- X */
- X if(mscore < hscore)
- X gainfac = (double)(mscore - hscore - safelead) / P_MAXROLL;
- X else
- X gainfac = (double)(plr[comp].p_score - hscore - safelead) / P_MAXROLL;
- X if(gainfac < 0)
- X gainfac = -gainfac;
- X gainfac = maxgainfac - gainfac;
- X if(gainfac < mingainfac)
- X gainfac = mingainfac;
- X
- X /*
- X ** Calculate the expectation value we can live with.
- X */
- X live = (int)(stay * gainfac);
- X if(xpct > live)
- X return True;
- X
- X return False;
- X
- X#undef TOOFAC
- X}
- X
- X/*
- X** crafty: call xx_crafty with original set of parameters
- X*/
- Xstatic boolean
- Xcrafty(comp, stay, xpct, pd)
- Xint comp, stay, xpct;
- Xdiceset *pd;
- X{
- X return xx_crafty(comp, stay, xpct, pd, WINMARGIN, 1.20, 0.85, 0.20);
- X}
- X
- X/*
- X** shakey: call xx_crafty with revised set of parameters
- X*/
- Xstatic boolean
- Xshakey(comp, stay, xpct, pd)
- Xint comp, stay, xpct;
- Xdiceset *pd;
- X{
- X /*
- X ** We have four distinct moods.
- X */
- X switch(plr[comp].p_mood) {
- X case 2: return xx_crafty(comp,stay,xpct,pd, P_STRAIGHT, 1.30, 0.75, 0.10);
- X case 3: return xx_crafty(comp,stay,xpct,pd, 2*OFFBOARD, 1.30, 0.80, 0.15);
- X case 4: return xx_crafty(comp,stay,xpct,pd, OFFBOARD, 1.20, 0.85, 0.20);
- X default:return xx_crafty(comp,stay,xpct,pd, OFFBOARD, 1.30, 0.75, 0.10);
- X }
- X}
- X
- X/*
- X** zeno: uses ratio of distance to finish over total distance
- X*/
- X/*ARGSUSED*/
- Xstatic boolean
- Xzeno(comp, stay, xpct, pd)
- Xint comp, stay, xpct;
- Xdiceset *pd;
- X{
- X#define MINWANT (WINMARGIN-1)
- X#define SANITY (1.10) /* fudge factor for endgame sanity */
- X#define AVGTURN 400 /* empirical */
- X
- X int hscore, mscore, hc;
- X int lead, want;
- X double zenofac, riskfac, wantfac;
- X
- X mscore = plr[comp].p_score; /* ignore this turn */
- X hscore = highscore(comp, &hc); /* of best competitor */
- X zenofac = (double)hscore / winscore; /* distance ratio */
- X if(hc < comp) { /* leader had turn */
- X zenofac = (double)hscore /* distance ratio */
- X / (winscore * SANITY);
- X lead = (mscore-WINMARGIN) - hscore; /* positive when winning */
- X } else { /* leader's turn to come */
- X zenofac = (double)(hscore + AVGTURN) /* distance ratio */
- X / (winscore * SANITY);
- X lead = (mscore-WINMARGIN)-(hscore+AVGTURN); /* positive when winning */
- X }
- X
- X if(lead > 0) { /* we're winning */
- X riskfac = 0.90 + 0.35 * zenofac; /* 0.90 - 1.25 */
- X if(xpct < (int)(riskfac * stay)) /* not willing to risk it */
- X return False; /* hold */
- X wantfac = 1.5 - 1.4 * zenofac; /* 1.5 - 0.1 */
- X if((want = lead * wantfac) < MINWANT) /* magic greed limit */
- X want = MINWANT; /* ... but keep moving */
- X if(stay > want) /* we're satisfied */
- X return False; /* hold */
- X }
- X
- X else if(lead > -WINMARGIN) { /* it's a dead heat */
- X riskfac = 1.0 + 0.35 * zenofac; /* 1.00 - 1.35 */
- X if(xpct < (int)(riskfac * stay)) /* not willing to risk it */
- X return False; /* hold */
- X /* no greed test */
- X }
- X
- X else { /* we're losing */
- X riskfac = 1.1 - 0.35 * zenofac; /* 1.1 - 0.75 */
- X if(xpct < (int)(riskfac * stay)) /* not willing to risk it */
- X return False; /* hold */
- X wantfac = 0.2 + 0.7 * zenofac; /* 0.2 - 0.9 */
- X if((want = -lead * wantfac) < MINWANT) /* magic greed limit */
- X want = MINWANT; /* ... but keep moving */
- X if(stay > want) /* we're satisfied */
- X return False; /* hold */
- X }
- X
- X return True; /* roll again */
- X
- X#undef MINWANT
- X#undef SANITY
- X#undef AVGTURN
- X}
- X
- X/*
- X** goalie: strives for four goals:
- X** winscore, 6/5ths average, 3/5ths average, and pace leader
- X*/
- X/*ARGSUSED*/
- Xstatic boolean
- Xgoalie(comp, stay, xpct, pd)
- Xint comp, stay, xpct;
- Xdiceset *pd;
- X{
- X int cuscore, stscore, hiscore, hc;
- X int turnsleft, avscore, totneed, perturn;
- X int toolittle, tooclose;
- X double gainfac, avgturn;
- X
- X#define WAYBEHIND ((P_MAXROLL * winscore) / WINSCORE)
- X#define SANITY 0.50
- X#define MAXTURN (P_ACEMULT * P_3OKMULT)
- X
- X /*
- X ** Avoid starting out too far in the hole by not getting on board
- X ** way behind -- the leave-the-game algorithm will eventually "save"
- X ** us, but we pay a price. We know what the price is, so if we
- X ** reach the break-even point, we hold.
- X */
- X cuscore = plr[comp].p_score;
- X stscore = cuscore + stay;
- X if(plr[comp].p_onboard == False /* && stay >= ONBOARD */) {
- X hiscore = highscore(comp, (int *)0);
- X if(hiscore - stscore > WAYBEHIND) {
- X if(atbreakeven(comp, stscore, hiscore) == True)
- X return False; /* hold */
- X return True; /* desperation */
- X }
- X }
- X
- X /*
- X ** Some parameters depend on our mood.
- X */
- X switch(plr[comp].p_mood) {
- X case 2: /* most agressive */
- X toolittle = 3 * P_ACE;
- X tooclose = P_FIVE;
- X gainfac = 1.025;
- X break;
- X case 3: /* more agressive */
- X toolittle = 2 * P_ACE + P_FIVE;
- X tooclose = P_ACE;
- X gainfac = 1.050;
- X break;
- X default: /* normal */
- X toolittle = 2 * P_ACE;
- X tooclose = P_ACE + P_FIVE;
- X gainfac = 1.075;
- X break;
- X }
- X
- X /*
- X ** Never stop with too little points. If there's gain to be had, roll.
- X ** If it would be insane to roll again, don't.
- X */
- X if(stay <= toolittle)
- X return True;
- X if(xpct > (int)(gainfac * stay))
- X return True;
- X if(xpct < (int)(SANITY * stay))
- X return False;
- X
- X /*
- X ** If we're ahead or close to the high score, don't reroll. Definition
- X ** of close depends on whether the leader has already taken its turn this
- X ** round. We calculate the leader's average turn for use here or below.
- X */
- X if((hiscore = highscore(comp, &hc)) == 0)
- X return False;
- X if(hc < comp) {
- X if(hiscore - stscore <= tooclose)
- X return False;
- X avgturn = (double)hiscore / (turnnum + 1);
- X } else {
- X avgturn = (double)hiscore / turnnum;
- X if(hiscore - stscore <= tooclose - (int)avgturn)
- X return False;
- X }
- X if(avgturn < P_ACE) /* too low to believe */
- X avgturn = P_ACE;
- X else if(avgturn > P_STRAIGHT) /* too high to believe */
- X avgturn = P_STRAIGHT;
- X
- X /*
- X ** We're behind, so it's a race to one of our goals. We estimate how many
- X ** turns left in the game based on the leader's average turn. From that,
- X ** we figure out what we need per turn to reach a reasonable goal.
- X ** If we've got that much, we hold, otherwise we roll again.
- X */
- X if((turnsleft = (winscore - hiscore) / avgturn) <= 0)
- X turnsleft = 1;
- X
- X /*
- X ** Primary goal: strive for winscore.
- X */
- X if((totneed = winscore - cuscore) <= 0)
- X goto pace;
- X if((perturn = totneed / turnsleft) <= MAXTURN)
- X return (stay >= perturn) ? False: True;
- X
- X /*
- X ** Calculate our historical average score.
- X */
- X if((avscore = histavgplr(comp)) == 0) /* no record */
- X avscore = (3 * WINSCORE) / 4; /* fake one */
- X avscore = (avscore * winscore) / WINSCORE; /* derate */
- X
- X /*
- X ** Secondary goal: strive for 6/5ths of average.
- X */
- X if((totneed = (6 * avscore) / 5 - cuscore) <= 0)
- X goto pace;
- X if((perturn = totneed / turnsleft) <= MAXTURN)
- X return (stay >= perturn) ? False: True;
- X
- X /*
- X ** Tertiary goal: strive for 3/5ths of average.
- X */
- X if((totneed = (3 * avscore) / 5 - cuscore) <= 0)
- X goto pace;
- X if((perturn = totneed / turnsleft) <= MAXTURN)
- X return (stay >= perturn) ? False: True;
- X
- X /*
- X ** Last resort: try to keep ahead of leader.
- X ** Else, keep moving at an arbitrary pace.
- X */
- Xpace:
- X if((totneed = hiscore + WINMARGIN - cuscore) > 0)
- X if((perturn = totneed / turnsleft) <= MAXTURN)
- X return (stay >= perturn) ? False: True;
- X return (stay >= 2 * P_ACE) ? False : True;
- X
- X#undef WAYBEHIND
- X#undef SANITY
- X#undef MAXTURN
- X}
- X
- X/*
- X** best: use the temperament currently ranked best
- X*/
- Xstatic boolean
- Xbest(comp, stay, xpct, pd)
- Xint comp, stay, xpct;
- Xdiceset *pd;
- X{
- X static history *phist = 0;
- X static computer *last = 0;
- X register int n;
- X extern temper te_best;
- X extern computer *pkamelion;
- X
- X /*
- X ** If this is our first time through, or if we're not
- X ** pointing to the same computer as last time, look
- X ** for the top ranked computer. On occasion we might
- X ** not re-search for the top when we should, but this
- X ** should happen only rarely.
- X */
- X if(phist == 0 || last == 0 || phist->h_computer != last) {
- X last = 0;
- X for(phist = hist, n = 0;n < nhist;++n, ++phist) {
- X if(phist->h_computer == 0 || phist->h_computer == pkamelion)
- X continue;
- X if(phist->h_computer->c_temper == &te_best)
- X continue;
- X last = phist->h_computer;
- X break;
- X }
- X }
- X
- X /*
- X ** If we've got a best computer, use its temperament,
- X ** else we default to using the robot temperament.
- X */
- X if(last != 0)
- X return (last->c_temper->t_func)(comp, stay, xpct, pd);
- X return robot(comp, stay, xpct, pd);
- X}
- X
- X/*
- X** kamelion: should never be called
- X*/
- Xstatic boolean
- Xkamelion(comp, stay, xpct, pd)
- Xint comp, stay, xpct;
- Xdiceset *pd;
- X{
- X syslog(LOG_WARNING, "kamelion temperament called!");
- X return best(comp, stay, xpct, pd);
- X}
- X
- X/*
- X** schizo: pick another temperament randomly!
- X** intended for proxy players only
- X*/
- Xstatic boolean
- Xschizo(comp, stay, xpct, pd)
- Xint comp, stay, xpct;
- Xdiceset *pd;
- X{
- X int n;
- X extern int tempers;
- X extern temper *temptbl[];
- X
- X hesitate(100L, 1000L);
- X plr[comp].p_mood = randint(MAXMOOD); /* new mood every time */
- X n = randint(tempers - 1) - 1; /* schizo last -- don't pick it */
- X return (*temptbl[n]->t_func)(comp, stay, xpct, pd);
- X}
- X
- X/*
- X** temptbl: table of available temperaments
- X*/
- X
- Xtemper te_robot = { robot, "robot" };
- Xtemper te_antsy = { antsy, "antsy" };
- Xtemper te_tracker = { tracker, "tracker" };
- Xtemper te_chicken = { chicken, "chicken" };
- Xtemper te_gambler = { gambler, "gambler" };
- Xtemper te_crafty = { crafty, "crafty" };
- Xtemper te_shakey = { shakey, "shakey" };
- Xtemper te_zeno = { zeno, "zeno" };
- Xtemper te_goalie = { goalie, "goalie" };
- Xtemper te_best = { best, "best" };
- Xtemper te_schizo = { schizo, "schizo" };
- Xtemper te_kamelion = { kamelion, "kamelion" }; /* semi-dummy */
- X
- Xtemper *temptbl[] = {
- X &te_robot, &te_antsy, &te_tracker, &te_chicken, &te_gambler,
- X &te_crafty, &te_shakey, &te_zeno, &te_goalie, &te_best,
- X &te_schizo /* te_schizo must be last */
- X};
- X
- Xint tempers = sizeof temptbl / sizeof temptbl[0];
- END_OF_FILE
- if test 21222 -ne `wc -c <'tempers.c'`; then
- echo shar: \"'tempers.c'\" unpacked with wrong size!
- fi
- # end of 'tempers.c'
- fi
- echo shar: End of archive 3 \(of 8\).
- cp /dev/null ark3isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 8 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-